#include "TrueText/Config.h"
#include "BlittingFunction.h"
#include "TrueText/Error.h"
#include "PixelFormatHelpers.h"

namespace TrueText {

void BlittingFunction::BlitPixel(int intensity, void* dst, PixelFormat dstFormat) const
{
	// Check preconditions
#if defined(DEBUG) || defined(_DEBUG)
	if (intensity < 0 || intensity > 255)
		throw Error(L"Trying to blit pixel with intensity out of range");
#endif
	// Forward call to inheritor
	DoBlitPixel(intensity, dst, dstFormat);
}

// The very hardcore. Black magic
void BlittingFunction::DoBlitPixel(int intensity, void* dst, PixelFormat dstFormat) const
{
	// No need to blit anything in case of transparent drawing.
	if (GetColor().a == 0)
		return; 

	int intens;
	if (GetColor().a == 255)
		intens = intensity;
	else
		intens = static_cast<int>(static_cast<float>(intensity) * (static_cast<float>(GetColor().a) / 255.0f));

	Color c = GetPixelColor(dst, dstFormat);

	if (blendMode == BLEND_ALPHA_COMPOSE)
	{
		int old_a = c.a;
		c.a = intens + old_a - ((intens * old_a) / 255);
		c.r = (intens * GetColor().r + c.r * old_a * (255 - intens) / 255) / 255;
		c.g = (intens * GetColor().g + c.g * old_a * (255 - intens) / 255) / 255;
		c.b = (intens * GetColor().b + c.b * old_a * (255 - intens) / 255) / 255;
	}
	else if (blendMode == BLEND_MAX)
	{
		c.a = std::max(intens, c.a);
		c.r = std::max(GetColor().r, c.r);
		c.g = std::max(GetColor().g, c.g);
		c.b = std::max(GetColor().b, c.b);
	}
	else if (blendMode == BLEND_OVERWRITE)
	{
		c.a = intens;
		c.r = GetColor().r;
		c.g = GetColor().g;
		c.b = GetColor().b;
	}
	SetPixelColor(dst, dstFormat, c);
}

}